package com.googlecode.nacl_optimizer.elf.headers;

import java.util.Arrays;

import com.googlecode.nacl_optimizer.elf.types.Elf32Addr;
import com.googlecode.nacl_optimizer.elf.types.Elf32Half;
import com.googlecode.nacl_optimizer.elf.types.Elf32Off;
import com.googlecode.nacl_optimizer.elf.types.Elf32Word;

public class ElfHeader {
    private Ident ident;
    private FileTypeField type;
    private Machine machine;

    private Elf32Word version; // 4
    private Elf32Addr entry; // 4
    private Elf32Off phoff; // 4
    private Elf32Off shoff; // 4
    private Elf32Word flags; // 4
    private Elf32Half ehsize; // 2
    private Elf32Half phentsize; // 2
    private Elf32Half phnum; // 2
    private Elf32Half shentsize; // 2
    private Elf32Half shnum; // 2
    private Elf32Half shstrndx; // 2

    public Integer getShoff() {
        return shoff.getInteger();
    }

    public Integer getShnum() {
        return shnum.getInteger();
    }

    public Integer getShEntSize() {
        return shentsize.getInteger();
    }

    public  DataEncoding getEncoding() {
        return ident.getEncoding();
    }
    
    public ElfHeader(byte[] hbuff) {
        byte[] buff = hbuff;
        ident = new Ident(Arrays.copyOfRange(buff, 0, 16));
        buff = Arrays.copyOfRange(buff, 16, buff.length);
        type = FileTypeField.getType(new Elf32Half(ident.getEncoding(), buff));
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        machine = Machine.getMachine(new Elf32Half(ident.getEncoding(), buff));
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        version = new Elf32Word(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 4, buff.length);
        entry = new Elf32Addr(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 4, buff.length);
        phoff = new Elf32Off(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 4, buff.length);
        shoff = new Elf32Off(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 4, buff.length);
        flags = new Elf32Word(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 4, buff.length);
        ehsize = new Elf32Half(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        phentsize = new Elf32Half(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        phnum = new Elf32Half(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        shentsize = new Elf32Half(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        shnum = new Elf32Half(ident.getEncoding(), buff);
        buff = Arrays.copyOfRange(buff, 2, buff.length);
        shstrndx = new Elf32Half(ident.getEncoding(), buff);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("ident: ");
        sb.append(ident);
        sb.append("\n");
        sb.append("file type: ");
        sb.append(type);
        sb.append("\n");
        sb.append("machine: ");
        sb.append(machine);
        sb.append("\n");
        sb.append("version: ");
        sb.append(version);
        sb.append("\n");
        sb.append("entry: ");
        sb.append(entry);
        sb.append("\n");
        sb.append("program header table offset: ");
        sb.append(phoff);
        sb.append("\n");
        sb.append("section header table offset: ");
        sb.append(shoff);
        sb.append("\n");
        sb.append("flags: ");
        sb.append(flags);
        sb.append("\n");
        sb.append("Size of ELF headers: ");
        sb.append(ehsize);
        sb.append("\n");
        sb.append("Size of program headers: ");
        sb.append(phentsize);
        sb.append("\n");
        sb.append("Number of program headers: ");
        sb.append(phnum);
        sb.append("\n");
        sb.append("Size of section headers: ");
        sb.append(shentsize);
        sb.append("\n");
        sb.append("Number of section headers: ");
        sb.append(shnum);
        sb.append("\n");
        sb.append("Section header string table index: ");
        sb.append(shstrndx);
        sb.append("\n");

        return sb.toString();
    }
}
